﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;

namespace InterestCalculationBiz
{
   public static class LoanHandler
    {
        public static DataSet CalculateLoan(LoanProperties propObj)
        {
            /*
             Table Return 
             * PAYMENT SCHEDULE *find below*
             * Result *find below*
             * DifferenceTable *find in loanmethod class in Cal_Difference_dataTable*
             */
            DataSet ds = new DataSet();
            double advCharges = 0;
            advCharges = propObj.Principal + propObj.BrokerageFee + propObj.CreditSearchFee + propObj.MonthlyFee + propObj.SecurityFee;
            double _desiredACR = 0.48;
            /*do-all*/
             ds = do_All(_desiredACR, propObj, advCharges, "dd/MM/yyyy", 0, 0, true, true);
             ds = Result(propObj,ds, "dd/MM/yyyy");
                /**/
           
            return ds;
        }
        private static DataSet do_All(double _desiredACR,LoanProperties propObj,double advCharges,string DateFormat="",int NoofInstallment=0,double Repayment=0, Boolean isAdvance=true,Boolean isOutput=false,string advancevalue="",double TrailRate=0,Boolean isRepaymentReCalculate=true)
        {
            DataSet ds = new DataSet();
            DataTable _dtLoan = null;
            DataSet _dsDifference = null;
            DataTable _dtInterest = null;
            // do_all
            // Range("q24") = Round(Range("i4") * Range("d6") / 365, 8)
            //Calc_EMI
            //ACR
            //Range("I9") = Range("q23")
            //ACR
               
            double _repayment = LoanMethod.Repayment(_desiredACR, propObj.Frequency, propObj.LoanDuration, propObj.Principal,NoofInstallment,Repayment);
            double _trailrate =0;
            if (TrailRate == 0)
            {
                _trailrate = LoanMethod.trailRate(propObj.Frequency, propObj.InterestRate);
            }
            else {
                _trailrate = TrailRate;  
            }
            _dtLoan = LoanMethod.CalculateLoanTable(propObj.InterestRate, _repayment, propObj, advCharges, _trailrate * 100,NoofInstallment,isAdvance,advancevalue);
            _dsDifference = LoanMethod.Cal_Difference_dataTable(_dtLoan, propObj, advCharges, _repayment, propObj.InterestRate,"",NoofInstallment);
            double _preFirstInterest = 0;
            double _balance = 0;
            try
            {
                if (Convert.ToDouble(_dsDifference.Tables["DifferenceTable"].Rows[0]["PreInterestRate"]) > 0)
                {
                    _preFirstInterest = Convert.ToDouble(_dsDifference.Tables["DifferenceTable"].Rows[0]["PreInterestRate"]);
                }
            }
            catch (Exception)
            {
                _preFirstInterest = 0;
            }
            if (isRepaymentReCalculate)
            {
                _repayment = LoanMethod.InitialInstallment(propObj.InterestRate, propObj.Frequency, propObj.LoanDuration, advCharges, _preFirstInterest, propObj.MonthlyFee, NoofInstallment);
            }
            else {
                _repayment = Repayment;  
            }
            _dtLoan = LoanMethod.CalculateLoanTable(propObj.InterestRate, _repayment, propObj, advCharges, _trailrate * 100,NoofInstallment,isAdvance,advancevalue);
            _dsDifference = LoanMethod.Cal_Difference_dataTable(_dtLoan, propObj, advCharges, _repayment, propObj.InterestRate,"",NoofInstallment);
            _balance = LoanMethod.Balance(_dsDifference.Tables["DifferenceTable"]);

            //Calc_EMI

            _repayment =LoanMethod.Cal_EMI(_repayment, _balance, propObj.InterestRate, advCharges, _trailrate * 100, propObj,NoofInstallment,isAdvance,advancevalue);

            //ACR
            if (TrailRate == 0)
            {
                _trailrate = LoanMethod.ACR(propObj.Frequency, propObj.InterestRate / 100, Math.Round(_repayment,2), propObj, advCharges, NoofInstallment, isAdvance,advancevalue);
            }
            else {
                _trailrate = TrailRate; 
            }
            // //Range("I9") = Range("q23")
            double _comparisonRate = 0;
            double _compoundfactor = 0;
            _compoundfactor = LoanMethod.CompundeFactor(propObj.Frequency);
            _comparisonRate = _trailrate * _compoundfactor;
            // _comparisonRate = LoanMethod.ComparisonRate(propObj.Frequency, propObj.InterestRate);

            //Range("I9") = Range("q23")

            if (isRepaymentReCalculate)
            {
                _repayment = LoanMethod.RevisedRepayment(_comparisonRate * 100, propObj.Frequency, propObj.LoanDuration, propObj.Principal, NoofInstallment);
            }
            else {
                _repayment = Repayment;  
            }

            //ACR
            if (TrailRate == 0)
            {
                _trailrate = LoanMethod.ACR(propObj.Frequency, propObj.InterestRate / 100, _repayment, propObj, advCharges, NoofInstallment, isAdvance, advancevalue);
            }
            else {
                _trailrate = TrailRate;  
            }

            _dtLoan = LoanMethod.CalculateLoanTable(propObj.InterestRate, _repayment, propObj, advCharges, _trailrate * 100,NoofInstallment,isAdvance,advancevalue);
            _dsDifference = LoanMethod.Cal_Difference_dataTable(_dtLoan, propObj, advCharges, _repayment, propObj.InterestRate, DateFormat, NoofInstallment, isOutput);
            
            /*Recalculate Comparison rate for reapyment*/
            _comparisonRate = 0;
            _compoundfactor = 0;
            _compoundfactor = LoanMethod.CompundeFactor(propObj.Frequency);
            _comparisonRate = _trailrate * _compoundfactor;
            /**/
            _dtInterest = LoanMethod.Interest_Rate(propObj.InterestRate / 100, _comparisonRate, _trailrate, propObj);
          
            _dtInterest.TableName = "InterestTable";
             

           // _dtLoan = SetOutputFormat_loanTable(_dtLoan, DateFormat);
            _dtLoan.TableName = "LoanTable";
            ds.Tables.Add(_dtLoan);
            ds.Tables.Add(_dtInterest);
            ds.Merge(_dsDifference);
            
            return ds;
        }
        private static DataSet Result(LoanProperties propObj,DataSet dsAll,string DateFromat)
        {
            DataTable Result = new DataTable();
            double Repayment = 0;
            double Anualcostrate = 0;
            double TotalInterest = 0;
            Result.Columns.Add("Totalinterest");
            Result.Columns.Add("Repayment");
            Result.Columns.Add("Annualcostrate");
            DataRow drResult = Result.NewRow();
            DataTable payment = new DataTable();
            payment.Columns.Add("Payhash");
            payment.Columns.Add("Date");
            payment.Columns.Add("Amount");
            if (dsAll.Tables.Contains("LoanTable"))
            {
                if (dsAll.Tables["LoanTable"].Rows.Count > 0)
                {
                    for (int i = 0; i < dsAll.Tables["LoanTable"].Rows.Count; i++)
                    {
                        try { TotalInterest += Convert.ToDouble(dsAll.Tables["LoanTable"].Rows[i]["Interest"]); }
                        catch (Exception) { }
                        if (LoanMethod.IsNumeric(dsAll.Tables["LoanTable"].Rows[i]["Payhash"]))
                        {
                            DataRow drPayment = payment.NewRow();
                            drPayment[0] = dsAll.Tables["LoanTable"].Rows[i]["Payhash"];
                            drPayment[1] = LoanMethod.CDate(Convert.ToString(dsAll.Tables["LoanTable"].Rows[i]["Date"]), DateFromat) + '(' + Convert.ToDateTime(dsAll.Tables["LoanTable"].Rows[i]["Date"]).DayOfWeek.ToString() + ')';
                            drPayment[2] = dsAll.Tables["LoanTable"].Rows[i]["payment"];
                            payment.Rows.Add(drPayment);
                        }
                    }
                }
            }
            if (dsAll.Tables.Contains("DifferenceTable"))
            {
                if (dsAll.Tables["DifferenceTable"].Rows.Count > 0)
                {
                    drResult[0] = TotalInterest;
                    try
                    {
                        Repayment = Convert.ToDouble(dsAll.Tables["DifferenceTable"].Rows[0]["Repayment"]);
                    }
                    catch (Exception) { }
                }
                else {
                    drResult[0] = 0;
                }
            }else{
                drResult[0] = 0;
            }
            if (dsAll.Tables["InterestTable"].Rows.Count > 0)
            {
                try
                {
                    Anualcostrate = Math.Round(Convert.ToDouble(dsAll.Tables["InterestTable"].Rows[0]["ComparisonRate"]) * 100, 2);
                }
                catch (Exception) { }
            }
            drResult[1] = Repayment;
            drResult[2] = Anualcostrate;
            Result.Rows.Add(drResult);
            Result.TableName = "Result";
            payment.TableName = "Payment";
            DataSet ds = new DataSet();
            ds.Tables.Add(Result);
            ds.Tables.Add(payment);
            return ds; 
        }
    }
}
